<?php
declare(strict_types=1);
namespace Framework\Libs;
use Framework\Service;
use Swoole\Http\Request;
use Swoole\Table;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server as WebSocketServer;
use Swoole\Http\Server as HttpServer;
/**
 * //IDE_LOAD_START
 *
 * //IDE_LOAD_END
 // replace  swoole_table_attr
 */
class Event extends \stdClass
{
    protected Service $server;
    protected HttpServer|WebSocketServer $http_server;
    // replace swoole_table_public

    public function __construct()
    {
        $this->server = $_ENV["bizan"];
        $this->http_server = $this->server->http_server;
        // replace swoole_table
    }


    public function _T(string $name):Table
    {
       // replace table
    }

    public function SetConfig($name,$isjson,$value){
	    switch ($isjson){
             case 1:
                  $value= xn_json_encode($value);
               break;
              case 2:
                   $value= implode(',',$value);
                break;
         }
        $data = $this->T_Config->set($name,['Json'=>$isjson,'Value'=>$value]);
        return $value;
    }

    public function GetConfig($name,$def='')
    {
        $data = $this->T_Config->get($name);
        $value = $def;
        if(empty($data)){
            return $value;
        }
        switch ($data['Json']){
            case 1:
                $value= xn_json_decode($data['Value']);
                break;
            case 2:
                $value= explode(',',$data['Value']);
                break;
            default:
                $value =  $data['Value'];
        }
        return $value;
    }

    public function __get($name)
    {
        // replace models
    }


    public function server_stats($data, $frame)
    {
        $data = \Swoole\Coroutine::stats();
        $stats = $this->http_server->stats();
        $data['connections'] = $stats['connection_num'];
        $data['WorkerStatus'] = $stats['connection_num'];
        $this->sendToClient($frame->fd, xn_json_encode(['cmd' => 'server', 'data' => $data]));
    }


    public function extend($class, $cmd, $value)
    {

        if (isset($_ENV['_models'][$class])) {
            if (is_callable([$_ENV['_models'][$class], $cmd])) {
                $_ENV['_models'][$class]->$cmd($value);
            }
        }
    }

    public function reload()
    {
        // hook libs_event_reload.php
    }

    // hook libs_event_get_message.php

    public function Join($data)
    {
        // hook libs_event_join.php
        return $data;
    }
    public function Open(Request $data)
    {
        // hook libs_event_open.php
        return $data;
    }
    public function message(Frame $data)
    {
        // hook libs_event_open.php
        return $data;
    }

    /**
     * @title    sendToAll
     * 发送指定信息给所有客户端
     *
     * @param string $send_data
     * @param array $fd_array
     * 2020/5/30 11:04
     */
    public function sendToAll(string $send_data, array $fd_array = []): void
    {
        // hook libs_event_send_to_all_start.php
        $fd_array = $fd_array ? $fd_array : $this->http_server->connections;
        foreach ($fd_array as $fd) {
            // 需要先判断是否是正确的websocket连接，否则有可能会push失败
            $this->isOnline($fd) && $this->http_server->push($fd, $send_data);
        }
        // hook libs_event_send_to_all_end.php
    }

    /**
     * @title    sendToClient
     * 向指定客户端发送消息
     *
     * @param int $fd
     * @param string $send_data
     * 2020/5/30 11:05
     */
    public function sendToClient(int $fd, string $send_data)
    {
        $this->sendToAll($send_data, [$fd]);
        return true;
    }

    /**
     * @title   closeClient
     * 关闭指定客户端
     *
     * @param int $fd
     * 2020/5/30 11:06
     */
    public function closeClient(int $fd,bool $close=false)
    {
        // hook libs_event_close_client_start.php
        if($this->isOnline($fd) && $close==true){
           $this->http_server->disconnect($fd);
        }
        // hook libs_event_close_client_end.php
        return true;
    }

    /**
     * @title    isOnline
     * 指定客服端是否在线
     *
     * @param string $fd
     * @return bool
     */
    public function isOnline($fd)
    {
        // hook libs_event_is_online_start.php
       return $this->http_server->isEstablished($fd);
    }

    /**
     * @title    bindUid
     * 客户端绑定UID
     *
     * @param int $fd
     * @param int $uid
     */
    public function bindUid(int $fd, int $uid)
    {
        // hook libs_event_bind_uid_start.php

        $this->Ws->add_uid_fd($uid,$fd);
        // hook libs_event_bind_uid_end.php
        return true;
    }

    /**
     * @title    unbindUid
     * 客户端解绑用户 - -好像没什么用吧
     *
     * @param int $fd
     * @param int $uid
     */
    public function unbindUid(int $fd, int $uid)
    {
        // hook libs_event_unbind_uid_start.php
         $this->Ws->del_uid_fd($fd,$uid);
        // hook libs_event_unbind_uid_end.php
        return true;
    }

    /**
     * @title    isUidOnline
     * 用户在线客户端
     *
     * @param int $uid
     */
    public function isUidOnline(int $uid)
    {
        $is_online=false;
        // hook libs_event_is_uid_online_start.php
        $fds = $this->Ws->find_fd_by_uid($uid);
        foreach ($fds as $fd){
           $this->isOnline($fd) && $is_online = true;
        }
        // hook libs_event_is_uid_online_end.php
        return $is_online;
    }

    /**
     * @title    getClientIdByUid
     * UID查寻在线终端
     *
     * @param int|array $uid
     *
     */
    public function getClientIdByUid($uid)
    {
        // hook libs_event_get_clientid_by_uid_start.php
         $fds = $this->Ws->find_fd_by_uid($uid);
        // hook libs_event_get_clientid_by_uid_end.php
        return $fds;
    }



    /**
     * @title    getUidByClientId
     * 终端对应UID
     *
     * @param string $fd
     */
    public function getUidByClientId(int $fd)
    {
        // hook libs_event_getUidByClientId_start.php
        return $this->Ws->find_uid_by_fd($fd);
    }

    /**
     * @title    sendToUid
     * 向指定UID对应所有终端发送指定信息
     *
     * @param int|array $uid
     * @param string $send_data
     */
    public function sendToUid($uid, string $send_data)
    {
        // hook libs_event_send_to_uid_start.php
        $fds = $this->Ws->find_fd_by_uid($uid);
        !empty($fds) && $this->sendToAll($send_data,$fds);
    }

    /**
     * @title joinGroup
     * 客户端绑定分组
     *
     * @param int $fd
     * @param int $gid
     */
    public function joinGroup(int $fd, int $gid)
    {
        // hook libs_event_joinGroup_start.php
        $this->Ws->add_gid_fd($gid,$fd);
        // hook libs_event_joinGroup_end.php
    }


    /**
     * @title    ungroup
     * 解散分组
     *
     * @param int $fd
     * @param int $gid
     */
    public function unGroup(int $gid)
    {
        // hook libs_event_unGroup_start.php
        $this->Ws->unGroup($gid);
        // hook libs_event_unGroup_end.php
    }

    /**
     * @title    sendToGroup
     * 像指定组发送消息
     *
     * @param int $gid
     * @param string $send_data
     * @param array $exclude_fd
     * 2020/5/30 15:36
     */
    public function sendToGroup(int $gid, string $send_data,$unfd = -1)
    {
        // hook libs_event_send_to_group_start.php

        $_fds = $this->Ws->find_fd_by_gid($gid);
       if($unfd>-1){
           $fds=[];
           foreach ($_fds as $fd){
             $unfd!=$fd && $fds[]=$fd;
           }
           $this->sendToAll($send_data,$fds);
       }else{
           $this->sendToAll($send_data,$_fds);
       }
    }

    /**
     * @title    getUidListByGroup
     * 查询组里所有UID
     *
     * @param int $gid
     */
    public function getUidListByGroup(int $gid)
    {
        // hook libs_event_get_uid_list_by_group_start.php
        return $this->Ws->find_uid_by_gid($gid);
    }

    /**
     * @title    getClientIdListByGroup
     * 查询组里所有终端
     *
     * @param int $gid
     * 2020/5/30 15:36
     */
    public function getClientIdListByGroup(int $gid)
    {
        // hook libs_event_get_clientid_list_by_group_start.php
        return $this->Ws->find_fd_by_gid($gid);
    }

    /**
     * @title    getAllClientIdList
     * 查询所有终端
     */
    public function getAllClientIdList()
    {
        // hook libs_event_get_all_clientid_list_start.php
        return $this->http_server->connections;
    }

    /**
     * @title    getAllUidList
     * 查询所有UID
     */
    public function getAllUidList()
    {
        // hook libs_event_get_all_uid_list_start.php
        return $this->Ws->find_uid_by_fd();
    }

    /**
     * @title    getAllGroupList
     * 查询所有组
     */
    public function getAllGroupList()
    {
        // hook libs_event_get_all_group_list_start.php
        return $this->Ws->find_gid_by_uid();
    }

}